package cn.chenxiejia;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @version : V1.0
 * @program: maven
 * @ClassName: T3
 * @Description:
 * @Author: chenxiejia
 * @Date: 2022/2/7 14:45
 */
public class T3 {
    List<String> list = new ArrayList<>();
    Object o = new Object();

    public static void main(String[] args) {
        T3 t3 = new T3();

        new Thread(t3::add, "T1").start();
        new Thread(t3::add, "T2").start();
        new Thread(t3::add, "T3").start();
        new Thread(t3::add, "T4").start();
        new Thread(t3::count).start();
    }

    void add() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String na = Thread.currentThread().getName();
        for (int i = 0; i < 10; i++) {
//            一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时，一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
//            二、然而，当一个线程访问object的一个synchronized(this)同步代码块时，另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
//            三、尤其关键的是，当一个线程访问object的一个synchronized(this)同步代码块时，其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
//            四、第三个例子同样适用其它同步代码块。也就是说，当一个线程访问object的一个synchronized(this)同步代码块时，它就获得了这个object的对象锁。结果，其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
//            五、以上规则对其它对象锁同样适用.
            synchronized (this) {
                synchronized (o) {
                    String item = na + ":item" + i;
                    try {
                        TimeUnit.SECONDS.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(item);
                    list.add(item);
                    if (list.size() == 5) {
                        try {
                            o.notifyAll();
                            o.wait();

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    void count() {
        System.out.println("监控中......");

        synchronized (o) {
            try {
                o.wait();
                System.out.println("已经五个元素了");
                o.notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}
